home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
smaltalk
/
manchest.lha
/
MANCHESTER
/
manchester
/
2.2
/
Form-fromDigitizer.st
< prev
next >
Wrap
Text File
|
1993-07-24
|
7KB
|
191 lines
" NAME Form-fromDigitizer
AUTHOR Alan Wills <alan@cs.man.ac.uk>
FUNCTION read in forms from simple digitizer array
ST-VERSIONS
PREREQUISITES
CONFLICTS
DISTRIBUTION world
VERSION 1.1
DATE 22 Jan 1989
SUMMARY
This stuff is for converting pictures from the CAT group's image digitizing equipment
to a Form. It's rather Manchester-local at the moment. You need to use Granville Moore's
software to dump the picture from the digitizer into a 512x512 array of ascii. Then
you use this to pick it up.
See Form>>fromPic:level:range: for details.
alan@ux.cs.man.ac.uk"
'From Smalltalk-80, Version 2.2 of July 4, 1987 on 21 February 1988 at 6:07:22 pm'!
!Array class methodsFor: 'instance creation'!
readPicFrom: fileName
"(Form extent: 128@128)
fromPic: (Array readPicFrom: '../image.saved') level: 31 range: 13;
displayOn: Display
at: 128@128 clippingBox: Display boundingBox
rule: Form over mask: Form black"
"AlanPic _ Array readPicFrom: '../image.saved'"
"Answer a 512x512 Array with numbers initialized from
the external file named fileName. The file format is:
the image is always 512 x 512;
one character per pixel;
characters outside the range ' ' to ' '+63 should be ignored;
brightness is on a 6-bit scale, ' ' to ' '+63
"
| file m r c |
file _ FileStream oldFileNamed: fileName.
file readOnly.
m _ Array new: 512.
(1 to: 512) do: [:i| m at: 513 - i put: (r _ Array new:512).
(1 to: 512) do: [:j|
[c _ file next asInteger. c<32] whileTrue: [].
r at: j put: c - 32 ]].
file close.
^m! !
!Form methodsFor: 'printing'!
storeOn: aStream
"Append to the argument aStream a description of the receiver in the form:
Form extent:fromCompactArray:#()offset:"
"Some examples are
| s | s_ WriteStream on: (String new: 2000).
Form fromUser storeOn: s.
(Compiler evaluate: s contents) displayAt: 0@0.
| f | f_ FileStream fileNamed: 'alan.form'.
Form fromUser storeOn: f.
f close. f size
"
| stripe |
aStream nextPut: $(; nextPutAll: self species name; crtab: 1.
aStream nextPutAll: 'extent: '; print: self extent; crtab: 1.
aStream nextPutAll: 'fromCompactArray: #('.
1 to: height do:
[:i |
stripe _ self scanLineStringAt: i-1.
stripe oldRunEncoded storeOn: aStream.
aStream cr].
aStream nextPut: $); crtab: 1.
aStream nextPutAll: 'offset: '; print: self offset; nextPut: $)! !
!Form methodsFor: 'initialize-release'!
fromPic: a level: level range: range
| r masks layers masksSize blackLevel contrast maskSorts jj jjj l targetSize targetScale sj tsTop tsBottom |
"takes a 512x512 Array of bytes and turns it into a Form.
The bytes represent variable brightness on a scale 0-63.
If the form is smaller than 512x512, the image is shrunk appropriately."
"Display fromPic: AlanPic level: 31 range: 16."
"((Form extent: 256@256) bits: Display bits)
fromPic: AlanPic level: 30 range: 14"
"((Form extent: (Rectangle fromUserAspectRatio: 1@1) extent) bits: Display bits)
fromPic: AlanPic level: 30 range: 12"
"(Form extent: 128@128)
fromPic: (Array readPicFrom: '../image.saved') level: 31 range: 13;
displayOn: Display
at: 128@128 clippingBox: Display boundingBox
rule: Form over mask: Form black"
"ScheduledControllers background: fromUser"
"At each pixel, select the Form mask for the appropriate gray level.
(Form white ... Form gray ... Form black in Form class>masks.)
In large areas of all one brightness, the effect is to copy the mask onto the
destination form. In areas of varying brightness, the mask you copy from
varies, but the effect is nevertheless as good as you could get by most
methods.
(Remember that BitBlt always regards a mask as being fixed relative to the
origin of the destination form: so you're picking up the pixel of the mask
which is appropriate for that pixel on the destination for drawing that
shade.)
The 'appropriate grey level' is done by some offset and scaling arithmetic
on the levels given by the digitizer.
It's a bit slow to go through drawing each pixel by an individual call to
BitBlt, so I make up a separate picture for each shade of grey (7 of them).
Then I draw the pictures 'over' each other, each with its appropriate mask.
I actually do this line by line, rather than doing the picture all in one
lump: that way, if the target form is the Display, I can watch the picture
being built up. It takes about 4 minutes for a full-scale 512x512 picture.
For smaller scales, I sample the brightness at intervals. This is better
than scaling after the conversion using shrink or magnify: these methods
only sample the binary pixels at intervals, which can have nasty
interactions with the periods in the masks, and produce spurious lines and
clumps.
There are one or two minimizations of the arithmetic done in the loop:
rather than be converting between reals and integers a lot, I've used
Fractions, separating the denominators and numerators so as to save time
looking up coercions and finding gcds."
self extent > (512 @ 512)
ifTrue: [targetSize _ 512 @ 512. targetScale _ 1 asFraction]
ifFalse: [jj _ self extent x min: self extent y.
targetSize _ jj @ jj. targetScale _ 512/jj ].
tsTop _ targetScale numerator. tsBottom _ targetScale denominator.
maskSorts _ #(black veryDarkGray darkGray gray lightGray veryLightGray white).
masksSize _ maskSorts size.
masks _ Array new: masksSize.
1 to: masksSize do: [:i| masks at: i put: (Form perform: (maskSorts at: i))].
blackLevel _ level - range.
contrast _ masksSize / (range * 2).
layers _ Array new: masksSize.
(1 to: layers size) do: [:i| layers at: i put: (WordArray new: 512//16)].
(1 to: targetSize y) do: [:i| r _ a at: (i * targetScale) asInteger.
jj _ 1. jjj _ 32768. layers do: [:layer| layer atAllPut: 0]. sj _ 0.
"and now the speed-critical loop:"
1 to: targetSize x do: [:j| sj _ sj + tsTop.
l _ layers at: ((((((r at: (sj quo: tsBottom))
- blackLevel) asFraction * contrast)
truncated) min: masksSize) max: 1).
l at: jj put: ((l at: jj) bitOr: jjj).
jjj <= 1 ifTrue: [jj _ jj + 1. jjj _ 32768] ifFalse: [ jjj _ jjj // 2]].
self fill: (0 @ (i-1) extent: targetSize x @ 1)
rule: Form over
mask: Form white.
1 to: masksSize do: [:j|
self copyBits: (0@0 extent: targetSize x@1)
from: (Form extent: 512 @1 fromArray: (layers at: j) offset: 0@0)
at: 0 @ (i-1)
clippingBox: self boundingBox
rule: Form paint
mask: (masks at: j)]
].
^self! !
Form organization classify: #storeOn: under: 'fileIn/Out' asSymbol!
Form organization classify: #storeOn:base: under: 'fileIn/Out' asSymbol!
Form organization removeCategory: #printing!
!Form class methodsFor: 'instance creation'!
fileInFrom: aFileName
"retrieve a form dumped by storeOn:"
"(Form fileInFrom: 'alan.form') displayOn: Display at: 0@0
clippingBox: Display boundingBox rule: Form over mask: Form black"
| file form |
file _ FileStream oldFileNamed: aFileName.
form _ Compiler new evaluate: file in: nil to: nil notifying: nil ifFail: [].
^ form! !
" r6 goodies 24/Feb/88
"